home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
text
/
misc
/
paginate.lha
/
Paginate
/
Paginate.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-27
|
9KB
|
362 lines
/* Paginate.c Copyright © 1993 Fergus Duniho */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "NumToStr.c"
size_t seglen(char *s);
void overwrite (char *dest, char *str, size_t pos, size_t dlen, size_t slen);
char *justify (char *str, size_t length);
char *addstr (char *rstr, char *str);
void print_usage ();
void lineprint (char *line, int page, int lmar, int len);
char *convert (char *str, int page, int len);
char *timecnv (char *fmt, struct tm *tptr, size_t len);
struct tm *get_time ();
main (int argc, char *argv[]) {
struct tm *t; /* Time Pointer */
char c,
empty_str[] = "",
*header = empty_str,
*hd[3] = {empty_str, empty_str, empty_str},
*footer = "@C- #d -",
*ft[3] = {empty_str, empty_str, empty_str},
*lnfmt = empty_str; /* printf style format string for line numbering */
size_t i, /* Loop Counter */
j, /* General Purpose Variable */
top = 4, /* These 4 values represent 1 inch margins for an */
bot = 57, /* 8½ x 11 inch sheet of paper where each square */
lmar = 8, /* inch is 6 lines by 10 characters, which will be */
rmar = 65, /* printed on a printer which puts a ½ inch margin */
/* at the top and a ¼ inch margin on the side. */
bottom, /* Variable For Bottom Value Of Current Page */
page1 = 1, /* Page Number For First Page */
page, /* Variable That Keeps Track Of Page Number */
linenum, /* Line Number for Counting Lines on Page */
line = 1, /* Line Number for Counting Lines in Document */
linelen, /* Line Length For Headers & Footers */
tpage = 0, /* Flag that indicates whether there is a title page */
newline = 1, /* Flag which indicates start of a new line */
done = 0; /* Flag which indicates when to leave a pair of loops */
/* Parse Command Line For Argument Values */
for (i = 1; i < argc; i++)
if (argv[i][0] == '-')
switch (argv[i][1]) {
case 'H': /* Default Header */
header = argv[++i];
break;
case 'h':
if (argv[i][2] == '0') /* Even Header */
hd[0] = argv[++i];
else if (argv[i][2] == '1') /* Odd Header */
hd[1] = argv[++i];
else if (argv[i][2] == 'f') /* Header For 1st Page */
hd[2] = argv[++i];
break;
case 'F': /* Default Footer */
footer = argv[++i];
break;
case 'f':
if (argv[i][2] == '0') /* Even Footer */
ft[0] = argv[++i];
else if (argv[i][2] == '1') /* Odd Footer */
ft[1] = argv[++i];
else if (argv[i][2] == 'f') /* Footer For 1st Page */
ft[2] = argv[++i];
break;
case 'N':
lnfmt = argv[++i];
break;
case 'r': /* Right Margin */
rmar = atoi(argv[++i]);
rmar = (rmar >= 1) ? rmar : 1;
break;
case 'l': /* Left Margin */
lmar = atoi(argv[++i]);
lmar = (lmar >= 1) ? lmar : 1;
break;
case 't': /* Top Line */
top = atoi(argv[++i]);
top = (top >= 1) ? top : 1;
break;
case 'b': /* Bottom Line */
bot = atoi(argv[++i]);
break;
case 'p': /* Page Number */
page1 = atoi(argv[++i]);
break;
case 'T': /* Title Page */
tpage = 1;
break;
default:
print_usage ();
break;
}
else
print_usage ();
if (bot <= top) {
perror ("The bottom value should be greater than the top value.\n");
exit (0);
}
/* Set Values for Footer and Header Strings */
t = get_time();
footer = timecnv(footer, t, rmar);
header = timecnv(header, t, rmar);
if (hd[0] == empty_str)
hd[0] = header; /* Header For Even Pages */
else
hd[0] = timecnv(hd[0], t, rmar);
if (hd[1] == empty_str)
hd[1] = header; /* Header For Odd Pages */
else
hd[1] = timecnv(hd[1], t, rmar);
if (hd[2] == empty_str)
hd[2] = header; /* Header For The First Page */
else
hd[2] = timecnv(hd[2], t, rmar);
if (ft[0] == empty_str)
ft[0] = footer; /* Footer For Even Pages */
else
ft[0] = timecnv(ft[0], t, rmar);
if (ft[1] == empty_str)
ft[1] = footer; /* Footer For Odd Pages */
else
ft[1] = timecnv(ft[1], t, rmar);
if (ft[2] == empty_str)
ft[2] = footer; /* Footer For The First Page */
else
ft[2] = timecnv(ft[2], t, rmar);
page = page1;
/* Paginate Standard Input Into Standard Output */
while (!done) {
if (tpage) {
footer = header = empty_str; /* Turns header and footer off. */
tpage = 0; /* No more than one title page. */
page--; /* Assures that page will equal page1 next time round */
}
else {
j = (page == page1) ? 2 : (page & 1);
header = hd[j];
footer = ft[j];
}
bottom = (*footer == 0) ? bot : bot - 2;
for (linenum = 1; linenum < top; linenum++)
putchar ('\n');
if (*header != 0) {
lineprint (header, page, lmar, rmar);
putchar ('\n');
linenum += 2;
}
while (linenum <= bottom && !done) {
if ((c = getc(stdin)) != EOF) {
if (newline) {
if (lnfmt != empty_str)
printf (lnfmt, line++);
newline = 0;
}
if (c == 12)
break;
putchar (c);
if (c == '\n') {
linenum++;
newline = 1;
}
}
else
done = 1;
}
if (*footer != 0) {
for (; linenum <= bottom; linenum++)
putchar ('\n');
putchar ('\n');
lineprint (footer, page, lmar, rmar);
}
putchar (12);
page++;
}
}
void lineprint (char *line, size_t page, size_t lmar, size_t len) {
char *str1, *str2;
size_t i;
str1 = convert(line, page, len);
str2 = justify(str1, len);
for (i = 1; i < lmar; i++)
putchar (' ');
puts (str2);
free (str1);
free (str2);
}
void print_usage () {
fprintf (stderr,
"
Paginate V1.00
Copyright © 1993 Fergus Duniho\n\n"
"Usage: Paginate <infile >outfile -F/K,-f0/K,-f1/K,-ff/K,-H/K,-h0/K\n"
" -h1/K,-hf/K,-N/K,-t/K/N,-b/K/N,-l/K/N,-r/K/N,-p/K/N,-T/S\n"
"
-H -h0 -h1 -hf
Default, Even, Odd, and First Page Headers\n"
"
-F -f0 -f1 -ff
Default, Even, Odd, and First Page Footers\n"
"
-N
Line Number String
-t
Top Line
-b
Bottom Line
-p
First Page #\n"
"
-l
Left Margin
-r
Relative Right Margin
-T
Title page\n"
"\nDefault: Paginate -F \"@C- #d -\" -H \"\" -N \"\" -l 8 -r 65 -t 4 -b 57 -p 1\n");
exit (0);
}
char *convert (char *str, size_t page, size_t len) {
char *rstr = (char *)malloc(len + 1);
char *r = rstr;
while (*str != 0) {
if (*str != '#')
*rstr++ = *str;
else
switch (*(++str)) {
case '#':
*rstr++ = '#';
break;
case 'r':
rstr = addstr(rstr, roman(page, 0));
break;
case 'R':
rstr = addstr(rstr, roman(page, 1));
break;
case 'd':
rstr = addstr(rstr, itoa(page, 10));
break;
case 'o':
rstr = addstr(rstr, itoa(page, 8));
break;
case 'b':
rstr = addstr(rstr, itoa(page, 2));
break;
case 'x':
rstr = addstr(rstr, itoa(page, 16));
break;
}
str++;
}
*rstr = 0;
return r;
}
char *addstr (char *rstr, char *str) {
while ((*rstr++ = *str++) != 0);
return --rstr;
}
char *justify (char *str, size_t length) {
size_t pos = 0, len;
char *line = (char *)malloc(length + 1);
char *ch = line;
size_t i;
for (i = 0; i < length; i++)
*ch++ = ' ';
*ch = 0;
while (*str != 0) {
if (*str == '@') {
if (*(++str) == 'R')
pos = length - seglen(++str);
else if (*str == 'C')
pos = (length - seglen(++str)) / 2;
else if (*str == '-') {
if (isxdigit(*(++str))) {
if (isdigit(*str))
pos -= (*str - '0');
else if (islower(*str))
pos -= ((*str - 'a') + 10);
}
str++;
}
else {
if (isxdigit(*str)) {
if (isdigit(*str))
pos += (*str - '0');
else if (islower(*str))
pos += ((*str - 'a') + 10);
}
else if (*str == 'L')
pos = 0;
str++;
}
}
else {
len = seglen(str);
overwrite(line, str, pos, length, len);
str += len;
}
}
return line;
}
void overwrite (char *dest, char *str, size_t pos, size_t dlen, size_t slen) {
if (pos > dlen)
return;
dest += pos;
while (slen-- && *dest && *str)
*dest++ = *str++;
}
size_t seglen(char *s) {
size_t len = 0;
while (1) {
if (*s == '@')
if (*(++s) == '@')
len++;
else
return len;
else if (*s == 0)
return len;
else
len++;
s++;
}
}
char *timecnv (char *fmt, struct tm *tptr, size_t len) {
char *s;
if (*fmt == 0)
return fmt;
if ((s = (char *)malloc(len + 1)) == 0) {
perror ("Out of memory.");
exit (2);
}
if (strftime(s, len, fmt, tptr) == 0) {
fprintf (stderr, "The expansion of %s is too long.\n", fmt);
exit (2);
}
return s;
}
struct tm *get_time () {
time_t *tod;
time (tod);
return localtime(tod);
}